<?php
require_once('Cache/Lite.php');
require_once(dirname(__FILE__).'/../converter/jpg_cleaner_function.php');
require_once(dirname(__FILE__).'/../converter/createpkg.php');
require_once('HTTP_HEADER_UTIL.php');

class NicoSB {
	var $conf;
	var $m_cache_lite;
	
	var $patterns;
	
	function NicoSB($conf){
		$this->conf = $conf;
		$this->m_cache_lite = new Cache_Lite($conf->cacheOptions);
		
		$path = $this->conf->cachedir.'/patterns';
		$this->patterns = $this->load_patterns($path);
	}
	
	function var_dump($obj){
		echo "<pre>";
		var_dump($obj);
		echo "</pre>";
	}

	//GD
	function gd(){
		$url = (array_key_exists('u',$_GET))?htmlspecialchars($_GET['u']):"";
		if(strcmp($url,'')!=0){
			$img = @imagecreatefromjpeg($url);
			header("Content-Type: image/jpeg");
			imagejpeg($img);
			imagedestroy($img);
		}
	}
	
	function load_patterns($path){
		$patterns = array('rankingall'=>'','search'=>'');
		if(file_exists($path)){
			$contents = file_get_contents($path);
			//変数に戻す
			$patterns = unserialize($contents);
			
			if(is_array($patterns)){
				$patterns['rankingall'] = (array_key_exists('rankingall',$patterns))?htmlspecialchars_decode($patterns['rankingall'],ENT_QUOTES):'';
				$patterns['search'] = (array_key_exists('search',$patterns))?htmlspecialchars_decode($patterns['search'],ENT_QUOTES):'';
			}
		}
		return $patterns;
	}
	
	function patterns(){
		$path = $this->conf->cachedir.'/patterns';
		$patterns = array('rankingall'=>'','search'=>'');
		
		$cmd = (array_key_exists('cmd',$_POST))?htmlspecialchars($_POST['cmd']):'';
		$password = (array_key_exists('password',$_POST))?htmlspecialchars($_POST['password']):'';
		
		if(strcmp($password,$this->conf->admin_password)!=0){
			$xml = "<nicosb>\n</nicosb>\n";
		}
		else {
			if(strcmp($cmd,'save')==0){
				$patterns['rankingall'] = (array_key_exists('rankingall',$_POST))?htmlspecialchars($_POST['rankingall']):'';
				$patterns['search'] = (array_key_exists('search',$_POST))?htmlspecialchars($_POST['search']):'';
				
				//変更したのでシリアライズして保存
				$contents = serialize($patterns);
				file_put_contents($path,$contents);
			}
			else{
				$patterns = $this->load_patterns($path);
			}
			
			$xml = "<nicosb>\n"
					."<rankingall>".htmlspecialchars($patterns['rankingall'],ENT_QUOTES)."<rankingall>\n"
					."<search>".htmlspecialchars($patterns['search'],ENT_QUOTES)."<search>\n"
					."</nicosb>\n";
		}
		
		//画面に出力
		header('Content-type: application/java');
		echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
		echo $xml;
	}
	
	//ログイン
	function login($mail,$password){
		// 引数
		$login_params = array(	"site"=>'niconico',
								"next_url" => "",
								"mail" =>$mail,
								"password" =>$password);
		//ログイン
		$cookiefname = tempnam($this->conf->cachedir, "cookie");
		$fp = fopen($cookiefname, "wb");
		$ch = curl_init($this->conf->login);
		
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);//サーバ証明書の検証をしない
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
		curl_setopt($ch, CURLOPT_COOKIEJAR, "cookie");
		curl_setopt($ch, CURLOPT_POST, true);
		curl_setopt($ch, CURLOPT_POSTFIELDS, $login_params);
		curl_setopt($ch, CURLOPT_WRITEHEADER, $fp);
		curl_exec($ch);
		fclose($fp);

		if(curl_errno($ch)!=0){
			echo curl_error($ch)."<br>";
			exit;
		}
		curl_close($ch);

		//クッキーのファイル名を返す
		return $cookiefname;
	}
	
	//ランキング取得
	function getRankingAll($cookiefname){
		if(strcmp($cookiefname,"")==0) return;
		
		$tmpfname2 = tempnam($this->conf->cachedir, "ranking_all");
		
		$fp = fopen($tmpfname2,"wb");
		$ch = curl_init($this->conf->ranking_all);
		curl_setopt($ch, CURLOPT_FILE,$fp);
		curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1);
		curl_setopt($ch, CURLOPT_COOKIEJAR,"cookie");
		curl_setopt($ch, CURLOPT_COOKIEFILE,$cookiefname);
		curl_exec($ch);
		fclose($fp);
		curl_close($ch);
		
		//TODO 正規表現でタイトル 作者コメント 画像を取得
		$contents = file_get_contents($tmpfname2);

		unlink($tmpfname2);
		
		preg_match_all ($this->patterns['rankingall'],$contents,$matches);
		
		$ranking_allArray = array();
		//ID取得
		foreach($matches[1] as $key => $tmp){
			$ranking_allArray[] = new Movie();
			$ranking_allArray[$key]->id = $tmp;
		}
		
		//サムネイルのURL
		foreach($matches[2] as $key => $tmp){
			$ranking_allArray[$key]->img = $tmp;
		}

		//タイトル取得
		foreach($matches[3] as $key => $tmp){
			$ranking_allArray[$key]->title = $tmp;
		}
				
		//パケット数
		foreach($matches[1] as $key => $tmp){
			$ranking_allArray[$key]->max_file_cnt = $this->getFileCnt($tmp);
		}
		
		//XMLで内容を返す
		$xml = $this->createMovieXML($ranking_allArray);

		//画面に出力
		header('Content-type: application/java');
		echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
		echo $xml;
	}

	//$sm_idに対する$service_typeを取得
	function getServiceType($sm_id){
		$service_type = '';
		foreach ($this->conf->service_types as $key => $val) {
			if(strcmp($val,'')!=0){
				$pos =strpos($sm_id,$key);
				if($pos !== false){
					$service_type = $val;
					break;
				}
			}
		}
		return $service_type;
	}
	
	//コメント取得
	//http://tetetep.blog112.fc2.com/blog-entry-181.html
	function getComment($cookiefname,$sm_id){
		if(strcmp($cookiefname,'')==0) return;
		
		$service_type = $this->getServiceType($sm_id);
		
		//$sm_id が niconicoでは無かった場合
		if(strcmp($this->conf->service_types['niconico'],$service_type)!=0){
			//空のコメントXMLを返す
			$comment = "<?xml version='1.0' encoding='UTF-8'?>\n<packet></packet>";
			header('Content-type: application/java');
			echo $comment;
			return;
		}
		
		$params = array("v"=>$sm_id);
								
		$tmpfname2 = tempnam($this->conf->cachedir, "getflv");
		
		$fp = fopen($tmpfname2,"wb");
		$ch = curl_init($this->conf->getflv_url);
		curl_setopt($ch, CURLOPT_FILE,$fp);
		curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1);
		curl_setopt($ch, CURLOPT_COOKIEJAR,"cookie");
		curl_setopt($ch, CURLOPT_COOKIEFILE,$cookiefname);
		curl_setopt($ch, CURLOPT_POST, true);
		curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
		curl_exec($ch);
		fclose($fp);
		curl_close($ch);

		//APIから返されたパラメータを読み込む & URLデコード
		$tmpcontents = urldecode(file_get_contents($tmpfname2));
		unlink($tmpfname2);
		
		//正規表現で各パラメータを抽出
		$tmpparam = new NicoapiParam();
		//ToDo 他のパラメータは今は使わないので省略
		{
			$pattern = "/thread_id=([^&]+)&/";
			preg_match($pattern,$tmpcontents,$matches);
			$tmpparam->thread_id = (array_key_exists('1',$matches))?$matches[1]:'';
		}
		{
			$pattern = "/ms=([^&]+)&/";
			preg_match($pattern,$tmpcontents,$matches);
			$tmpparam->ms = (array_key_exists('1',$matches))?$matches[1]:'';
		}
		
		if((strcmp($tmpparam->thread_id,'')==0)||(strcmp($tmpparam->ms,'')==0)){
			//エラー
			//空のコメントXMLを返す
			$comment = "<?xml version='1.0' encoding='UTF-8'?>\n<packet></packet>";
			header('Content-type: application/java');
			echo $comment;
			return;
		}
		
		//$tmpparam->ms に '<thread res_from="-100" version="20061206" thread="1182348928" />' をPOST
		$params = '<thread res_from="-100" version="20061206" thread="'.$tmpparam->thread_id.'" />';

		$tmpfname3 = tempnam($this->conf->cachedir, "comment");
		
		$fp = fopen($tmpfname3,"wb");
		$ch = curl_init($tmpparam->ms);
		curl_setopt($ch, CURLOPT_FILE,$fp);
		curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1);
		curl_setopt($ch, CURLOPT_COOKIEJAR,"cookie");
		curl_setopt($ch, CURLOPT_COOKIEFILE,$cookiefname);
		curl_setopt($ch, CURLOPT_POST, true);
		curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
		curl_exec($ch);
		fclose($fp);
		curl_close($ch);
		
		$comment = file_get_contents($tmpfname3);
		unlink($tmpfname3);
				
		header('Content-type: application/java');
		echo $comment;
	}
	
	//ランキング
	function ranking_all(){
		if (strcmp($this->patterns['rankingall'],'')==0){
			header('Content-type: application/java');
			echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
			echo "<nicosb></nicosb>";
			exit;
		}
	
		$mail 		= (array_key_exists("mail",$_POST))?$_POST["mail"]:'';
		if(strcmp($mail,'')==0){
			$mail 	= (array_key_exists("mail",$_GET))?$_GET["mail"]:'';
		}
		
		$password 	= (array_key_exists("password",$_POST))?$_POST["password"]:'';
		if(strcmp($password,'')==0){
			$password 	= (array_key_exists("password",$_GET))?$_GET["password"]:'';
		}
		
		$mail		= htmlspecialchars($mail);
		$password	= htmlspecialchars($password);

		//アクセス許可・拒否アドレスチェック
		if($this->denyallow_check($mail)==false){
			header('Content-type: application/java');
			echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
			echo "<nicosb></nicosb>";
			exit;
		}
		
		if( (strcmp($mail,"")!=0)&&(strcmp($password,"")!=0) ){
			//ログイン
			$cookie = $this->login($mail,$password);
			//ランキング取得
			$this->getRankingAll($cookie);
			unlink($cookie);
		}
		else{
			header('Content-type: application/java');
			echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
			echo "<nicosb></nicosb>";
		}
	}
	
	//コメント
	function comment(){
		$mail 		= (array_key_exists("mail",$_POST))?$_POST["mail"]:'';
		if(strcmp($mail,'')==0){
			$mail 		= (array_key_exists("mail",$_GET))?$_GET["mail"]:'';
		}
		$password 	= (array_key_exists("password",$_POST))?$_POST["password"]:'';
		if(strcmp($password,'')==0){
			$password 	= (array_key_exists("password",$_GET))?$_GET["password"]:'';
		}
		
		$sm_id 	= (array_key_exists("sm_id",$_POST))?$_POST["sm_id"]:'';
		if(strcmp($sm_id,'')==0){
			$sm_id 	= (array_key_exists("sm_id",$_GET))?$_GET["sm_id"]:'';
		}
		
		$mail		= htmlspecialchars($mail);
		$password	= htmlspecialchars($password);
		$sm_id      = htmlspecialchars($sm_id);
		
		//アクセス許可・拒否アドレスチェック
		if($this->denyallow_check($mail)==false){
			//空のコメントXMLを返す
			$comment = "<?xml version='1.0' encoding='UTF-8'?>\n<packet></packet>";
			header('Content-type: application/java');
			echo $comment;
			exit;
		}
		
		if( (strcmp($mail,'')!=0)&&(strcmp($password,'')!=0) ){
			//ログイン
			$cookie = $this->login($mail,$password);
			//コメント取得
			$this->getComment($cookie,$sm_id);
			unlink($cookie);
		}
		else{
			//空のコメントXMLを返す
			$comment = "<?xml version='1.0' encoding='UTF-8'?>\n<packet></packet>";
			header('Content-type: application/java');
			echo $comment;
			exit;
		}
	}
	
	//検索
	function search(){
		if (strcmp($this->patterns['search'],'')==0){
			header('Content-type: application/java');
			echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
			echo "<nicosb></nicosb>";
			exit;
		}

		$mail 		= (array_key_exists("mail",$_POST))?$_POST["mail"]:'';
		if(strcmp($mail,'')==0){
			$mail 	= (array_key_exists("mail",$_GET))?$_GET["mail"]:'';
		}
		
		$password 	= (array_key_exists("password",$_POST))?$_POST["password"]:'';
		if(strcmp($password,'')==0){
			$password 	= (array_key_exists("password",$_GET))?$_GET["password"]:'';
		}
		
		$word 	= (array_key_exists("word",$_POST))?$_POST["word"]:'';
		if(strcmp($word,'')==0){
			$word 	= (array_key_exists("word",$_GET))?$_GET["word"]:'';
		}
		
		$type 	= (array_key_exists("type",$_POST))?$_POST["type"]:'';
		if(strcmp($type,'')==0){
			$type 	= (array_key_exists("type",$_GET))?$_GET["type"]:'';
		}
				
		$mail		= htmlspecialchars($mail);
		$password	= htmlspecialchars($password);
		$word		= htmlspecialchars($word);
		$type		= htmlspecialchars($type);
		

		//アクセス許可・拒否アドレスチェック
		if($this->denyallow_check($mail)==false){
			header('Content-type: application/java');
			echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
			echo "<nicosb></nicosb>";
			exit;
		}

		if( (strcmp($mail,"")!=0)&&(strcmp($password,"")!=0) ){
			//ログイン
			$cookie = $this->login($mail,$password);
			//検索
			$this->getSearch($type,$word,$cookie);
			unlink($cookie);
		}
		else{
			header('Content-type: application/java');
			echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
			echo "<nicosb></nicosb>";
		}
	}
	
	//アクセス許可・拒否アドレスチェック
	function denyallow_check($mail){
		$ret = true;
		//アクセス許可アドレスチェック
		if(array_search($mail,$this->conf->allow_mails)===false){
			//許可アドレスじゃない
			if(strcmp($this->conf->allow_mails[0],'')!=0){
				$ret = false;
			}
			else{
				//アクセス拒否アドレスチェック
				if(array_search($mail,$this->conf->deny_mails)!==false){
					//見つかった
					$ret = false;
				}
			}
		}
		return $ret;
	}
	
	//検索結果XML
	function getSearch($type,$word,$cookiefname){
		if(strcmp($cookiefname,"")==0) return;
		$p = 1;
		$url='';
		if(strcmp($type,'1')==0){
			//タグ検索
			$url = $this->conf->tagsearch.urlencode($word).'?page='.$p;
		}
		else{
			//キーワード検索
			$url = $this->conf->wordsearch.urlencode($word).'?page='.$p;
		}
		
		$tmpfname2 = tempnam($this->conf->cachedir, "search");
		
		$fp = fopen($tmpfname2,"wb");
		$ch = curl_init($url);
		curl_setopt($ch, CURLOPT_FILE,$fp);
		curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1);
		curl_setopt($ch, CURLOPT_COOKIEJAR,"cookie");
		curl_setopt($ch, CURLOPT_COOKIEFILE,$cookiefname);
		curl_exec($ch);
		fclose($fp);
		curl_close($ch);
		
		//TODO 正規表現でタイトル 作者コメント 画像を取得
		$contents = file_get_contents($tmpfname2);
		unlink($tmpfname2);

		preg_match_all ($this->patterns['search'],$contents,$matches);
		
		$searchArray = array();
		//ID取得
		foreach($matches[1] as $key => $tmp){
			$searchArray[] = new Movie();
			$searchArray[$key]->id = $tmp;
		}
		//タイトル取得
		foreach($matches[2] as $key => $tmp){
			$searchArray[$key]->title = $tmp;
		}
		
		//サムネイルのURL
		foreach($matches[3] as $key => $tmp){
			$searchArray[$key]->img = $tmp;
		}
		
		//パケット数
		foreach($matches[1] as $key => $tmp){
			$searchArray[$key]->max_file_cnt = $this->getFileCnt($tmp);
		}
		
		//XMLで内容を返す
		$xml = $this->createMovieXML($searchArray);

		//画面に出力
		header('Content-type: application/java');
		echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
		echo $xml;
	}
	
	//指定されたIDのフォルダの中のjarファイルの数を取得する
	function getFileCnt($sm_id){
		$cnt = 0;
		$dir = $this->conf->basedir.'/'.$sm_id.'/';
		if(is_dir($dir)){
			if(!($cnt = $this->m_cache_lite->get("cnt_".$sm_id))){
				//一覧取得
				$cnt = 0;
				$d = dir($dir);
				while (false !== ($entry = $d->read())) {
					//カレントと上位階層を除外
		            if(!((strcmp($entry,'.')==0) || (strcmp($entry,'..')==0))){
		            	//jarファイルだけカウント
		            	if(strpos($entry,'.jar')!==false){
					   		$path = $dir."/".$entry;
					   		if((is_file($path))&&(filesize($path)==0)) {
					   			$cnt++;
					   		}
				   		}
					}
				}
				$d->close();
				
				//キャッシュへ保存
				if($cnt > 0){
					$this->m_cache_lite->save( "{$cnt}" );
				}
			}
		}
		return $cnt;
	}
	
	function createMovieXML($movieArray){
		$xml = "<nicosb>\n";
		foreach($movieArray as $key => $movie){
			$xml .= "<movie>\n";
			
			$xml .= "<id>".$movie->id."</id>\n";
			$xml .= "<max_file_cnt>".$movie->max_file_cnt."</max_file_cnt>\n";
			$xml .= "<date>".$movie->date."</date>\n";
			if(strcmp($this->conf->img_type,'jpg')!=0){
				$xml .= "<img>".$movie->img."</img>\n";
			}else{
				//$xml .= "<img>".$this->conf->base_url."gd.php?u=".urlencode($movie->img)."</img>\n";
				$xml .= "<img>".$movie->img."</img>\n";
			}
			$xml .= "<title>".$movie->title."</title>\n";
			$xml .= "<time>".$movie->time."</time>\n";
			$xml .= "<comment>".$movie->comment."</comment>\n";
			$xml .= "<res>".$movie->res."</res>\n";
		
			$xml .= "</movie>";
		}
		$xml .= "</nicosb>";
		
		return $xml;
	}
	
	//キャッシュリクエスト
	function cache(){
		$sm_id 	= (array_key_exists("sm_id",$_POST))?$_POST["sm_id"]:'';
		if(strcmp($sm_id,'')==0){
			$sm_id 	= (array_key_exists("sm_id",$_GET))?$_GET["sm_id"]:'';
		}
		$sm_id      = htmlspecialchars($sm_id);
		
		//smXXXXXX形式かチェックする
		if(strcmp($sm_id,'')!=0){
			$match = array();
			$flg = preg_match('/^[a-z][a-z][0-9]+/',$sm_id,$match);
			if(($flg!==false)&&($flg==0)){
				return;
			}
		}
		
		$cnt = 0;
		if(strcmp($sm_id,"")!=0){
			//リクエストキューに登録
			$cnt = $this->addCacheQueue($sm_id);
		}
		else{
			//キューファイルを読み込む
			$queue = array();
			$path = $this->conf->cachedir.'/cachequeue';
			if(file_exists($path)){
				$contents = file_get_contents($path);
				//シリアル化されたキューを変数に戻す
				$queue = unserialize($contents);
			}
			//キューイングされている数を取得
			$cnt = count($queue);
		}
		
		header('Content-type: application/java');
		echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
		echo "<nicosb>\n<request_queue>".$cnt."</request_queue>\n</nicosb>";
	}
	
	//キャッシュリクエストをキューに登録
	function addCacheQueue($sm_id,$checkflg = true){
		$cnt = 0;
		
		$queue = array();
		
		//キューファイルを読み込む
		$path = $this->conf->cachedir.'/cachequeue';
		if(file_exists($path)){
			$contents = file_get_contents($path);
			//シリアル化されたキューを変数に戻す
			$queue = unserialize($contents);
		}
		
		if($checkflg==true){
			//サービスタイプを取得
			$service_type = $this->getServiceType($sm_id);
			
			//youtubeでは無い場合数チェック
			if(strcmp($this->conf->service_types['youtube'],$service_type)!=0){
				//すでにキャッシュしている数をチェック
				if(count($queue) >= $this->conf->queue_max){
					//超えているので要求を無視
					$cnt = count($queue);
					return $cnt;
				}
			}
			
			//flvのキャッシュをチェックする
			$fname = $this->conf->cachedir.'/'.$sm_id.'.'.$this->getExt($sm_id);
			if(!file_exists($fname)){
				//flvのキャッシュが無い
				$flg = false;
				if(count($queue)>0){
					//すでに登録されていないかチェックする
					foreach($queue as $id){
						if(strcmp($sm_id,$id)==0){
							$flg = true;
						}
					}
				}
				
				if($flg==false){
					//未登録なのでキューに追加
					$queue[] = $sm_id;
					//変更したのでシリアライズして保存
					$contents = serialize($queue);
					file_put_contents($path,$contents);
				}
			}
		}
		else{
			//強制的にキューに追加
			$queue[] = $sm_id;
			//変更したのでシリアライズして保存
			$contents = serialize($queue);
			file_put_contents($path,$contents);
		}
		
		//キューイングされている数を取得
		$cnt = count($queue);

		return $cnt;
	}
	
	function watch($cookiefname,$sm_id){
		$cookie2 = tempnam($this->conf->cachedir, "cookie2");
		$fp = fopen($cookie2, "w");
		$ch = curl_init($this->conf->watch_url.$sm_id);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
		curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie');
		curl_setopt($ch, CURLOPT_COOKIEFILE, $cookiefname);
		curl_setopt($ch, CURLOPT_WRITEHEADER, $fp);
		curl_exec($ch);
		fclose($fp);
		curl_close($ch);
		
		return $cookie2;
	}
	
	//flvのURL取得
	function getFlvURL($cookiefname,$sm_id){
		if(strcmp($cookiefname,"")==0) return;
		
		$params = array("v"=>$sm_id);
								
		$tmpfname2 = tempnam($this->conf->cachedir, "getflv");
		
		$fp = fopen($tmpfname2,"wb");
		$ch = curl_init($this->conf->getflv_url);
		curl_setopt($ch, CURLOPT_FILE,$fp);
		curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1);
		curl_setopt($ch, CURLOPT_COOKIEJAR,"cookie");
		curl_setopt($ch, CURLOPT_COOKIEFILE,$cookiefname);
		curl_setopt($ch, CURLOPT_POST, true);
		curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
		curl_exec($ch);
		fclose($fp);
		curl_close($ch);

		//APIから返されたパラメータを読み込む & URLデコード
		$tmpcontents = urldecode(file_get_contents($tmpfname2));
		unlink($tmpfname2);
		
		//正規表現で各パラメータを抽出
		$tmpparam = new NicoapiParam();
		//ToDo 他のパラメータは今は使わないので省略
		{
			$pattern = "/url=([^&]+)&/";
			preg_match($pattern,$tmpcontents,$matches);
			$tmpparam->url = $matches[1];
		}
		
		return $tmpparam->url;
	}
	
	//flvのダウンロード
	function flvDownload($url,$flvpath,$cookiefname=''){
		$fp = fopen($flvpath,'wb');
		$ch = curl_init($url);
		curl_setopt($ch, CURLOPT_FILE, $fp);
		curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
		if(strcmp($cookiefname,'')!=0){
			curl_setopt($ch, CURLOPT_COOKIEJAR,'cookie');
			curl_setopt($ch, CURLOPT_COOKIEFILE,$cookiefname);
		}
		curl_exec($ch);
		fclose($fp);
		curl_close($ch);
	}
	
	//sm_idに対する拡張子を取得
	function getExt($sm_id){
		$ret = "flv";
		
		//[ToDo] '_'が含まれていた場合は、拡張子をflvとする。
		if(strpos($sm_id,'_')!==false){
			if(strpos($sm_id,'nm')!==false){
				$ret = "swf";
			}
			else if(strpos($sm_id,'sm')!==false){
				$ret = "flv";
			}
		}
		
		return $ret;
	}
	
	//flvをキャッシュ＆変換 (クーロンからコマンドラインで呼び出される)
	function wget(){
		if($_SERVER["argc"]!=2) return;
		
		$argv = $_SERVER["argv"];
		$service_type = '';
		$sm_id1 = $argv[1];
		$sm_id2 = $argv[1];
		foreach ($this->conf->service_types as $key => $val) {
			if(strcmp($val,'')!=0){
				$pos =strpos($argv[1],$key);
				if($pos !== false){
					$service_type = $val;
					$sm_id1 = str_replace($key.'_','',$sm_id1);
					break;
				}
			}
		}
		
		$flvpath = $this->conf->cachedir.'/'.$sm_id2.'.'.$this->getExt($sm_id1);
		if((file_exists($flvpath))&&(filesize($flvpath)==0)){
			//ダウンロードしっぱい
			@unlink($flvpath);
		}
		
		//flvが有るかチェック
		if(!file_exists($flvpath)){
			//無ければダウンロード
			//ToDo $this->conf->service_types で振り分けて あとでプラグイン形式とする
			if(strcmp($this->conf->service_types['niconico'],$service_type)==0){
				//niconico
				//クッキー１を取得
				$cookie1 = $this->login($this->conf->mail,$this->conf->password);
				
				//flvのURLを取得
				$url = $this->getFlvURL($cookie1,$sm_id1);
				
				//クッキー２を取得
				$cookie2 = $this->watch($cookie1,$sm_id1);

				//$cookie2と$urlをつかってflvをダウンロード
				$this->flvDownload($url,$flvpath,$cookie2);

				unlink($cookie2);
				unlink($cookie1);
			}
			else if(strcmp($this->conf->service_types['youtube'],$service_type)==0){
				//YouTube
				$url = $this->getYoutubeFlvURL( $sm_id1 );
				$this->getYoutubeFlv($url,$flvpath);
			}
		}
		
		//コンバーターを呼び出す
		$moviepkg = new CreateMoviePKG($this->conf);
		$moviepkg->create($flvpath,$sm_id2);
	}
	
	//クーロン(定期的に実行される)
	function cron(){
		$lock = $this->conf->cachedir.'/cron.lock';
		$queue = null;
		
		//[ToDo] 一時間前の cron.lockファイルは、異常なので削除
		$this->cronlock_clear($lock);
		
		//cron.lockファイルがあるかチェックする
		if(file_exists($lock)){
			return;
		}
		
		//作業中ロック
		//echo $lock."\n";
		$fp = fopen($lock, 'w');
		fputs($fp,'1');
		fclose($fp);
				
		//キューファイルを読み込む
		$path = $this->conf->cachedir.'/cachequeue';
		if(file_exists($path)){
			$contents = file_get_contents($path);
			//シリアル化されたキューを変数に戻す
			$queue = unserialize($contents);
		}
		
		//一番古い値を取り出す
		$sm_id = array_pop($queue);

		//wget & コンバート
		$cmd = 'php '.$this->conf->wget_php.' '.$sm_id;
		exec($cmd);
		
		//キャッシュをチェックする
		//$tmppath = $this->conf->basedir.'/'.$sm_id.'/';
		//if(is_dir($tmppath)){
			//変更したのでシリアライズして保存
			$contents = serialize($queue);
			file_put_contents($path,$contents);
		//}
		
		//キャッシュファイルをアップロード
		if(strcmp($this->conf->upload_type,'HTTP')===0){
			//[ToDo] HTTP
		}
		else if(strcmp($this->conf->upload_type,'FTP')===0){
			//FTP
			$this->ftp_upload($sm_id);
		}
		
		//変換失敗している物を削除
		$this->miss_cache_clean();
		
		//作業中ロックファイル削除
		@unlink($lock);
	}
	
	//変換失敗している物を削除
	function miss_cache_clean(){
		//srand();
		//1/1000 の確立で失敗キャッシュを整理する
		//$number = round(rand(1,1000));
		//if($number==500){
			if(is_dir($this->conf->basedir)){
				$dir = opendir($this->conf->basedir);
				while($file = readdir($dir)){
					//上ディレクトリでない場合のみ
					if((strcmp($file,'.')!=0)&&(strcmp($file,'..')!=0)){
						$path = $this->conf->basedir.'/'.$file;
						if(is_dir($path)){
							$sm_id = $file;
							$cnt = $this->getFileCnt($sm_id);
							if($cnt==0){
								//変換 失敗している
								//ディレクトリ削除
								$this->deleteDir($path);
								//強制的にキャッシュリクエストに追加
								$this->addCacheQueue($sm_id,false);
							}
						}
					}
				}
				closedir($dir);
			}
		//}
	}
	
	//過去のcron.lockファイルを削除する
	function cronlock_clear($path){
		//1時間前のファイルは削除
		if(file_exists($path)){
			$now     = time()-(1*60*60);
			$tmptime = filemtime($path);
			if($tmptime<$now){
				//削除
				unlink($path);
			}
		}
	}
	
	//ディレクトリ削除
	function deleteDir($rootPath){
		if(is_dir($rootPath)){
			$strDir = opendir($rootPath);
			while($strFile = readdir($strDir)){
				//ディレクトリでない場合のみ
				if($strFile != '.' && $strFile != '..'){
					@unlink($rootPath.'/'.$strFile);
				}
			}
			closedir($strDir);
			rmdir($rootPath);
		}
	}
	
	//キャッシュ化済みの一覧を返す
	function cachelist(){
		$rows = '';
		if(is_dir($this->conf->basedir)){
			$dir = opendir($this->conf->basedir);
			while($file = readdir($dir)){
				//上ディレクトリでない場合のみ
				if((strcmp($file,'.')!=0)&&(strcmp($file,'..')!=0)){
					if(is_dir($this->conf->basedir.'/'.$file)){
						$rows .= "<cache>\n<id>".$file."</id>\n</cache>\n";
					}
				}
			}
			closedir($dir);
		}
		
		header('Content-type: application/java');
		echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
		echo "<nicosb>\n"
			.$rows
			."</nicosb>";
	}
	
	//キャッシュの有無
	function cacheexists(){
		$sm_id 	= (array_key_exists("sm_id",$_POST))?$_POST["sm_id"]:'';
		if(strcmp($sm_id,'')==0){
			$sm_id 	= (array_key_exists("sm_id",$_GET))?$_GET["sm_id"]:'';
		}
		$sm_id      = htmlspecialchars(basename($sm_id));
		
		$exists = false;
		if(strcmp($sm_id,'')!=0){
			$exists = (is_dir($this->conf->basedir.'/'.$sm_id))?'true':'false';
		}
		
		header('Content-type: application/java');
		echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
		echo "<nicosb>\n"
			."<exists>".$exists."</exists>\n"
			."</nicosb>";
	}
	
	//レジスタ
	function register(){
		$host 	= (array_key_exists("host",$_POST))?$_POST["host"]:'';
		if(strcmp($host,'')==0){
			$host 	= (array_key_exists("host",$_GET))?$_GET["host"]:'';
		}

		$port 	= (array_key_exists("port",$_POST))?$_POST["port"]:'';
		if(strcmp($port,'')==0){
			$port 	= (array_key_exists("port",$_GET))?$_GET["port"]:'';
		}

		$audio_type 	= (array_key_exists("audio_type",$_POST))?$_POST["audio_type"]:'';
		if(strcmp($audio_type,'')==0){
			$audio_type 	= (array_key_exists("audio_type",$_GET))?$_GET["audio_type"]:'';
		}
				
		$host       = htmlspecialchars($host);
		$port       = htmlspecialchars($port);
		$audio_type = htmlspecialchars($audio_type);
		
		$register = array();
		//レジスタファイルを読み込む
		$path = $this->conf->cachedir.'/register';
		if(file_exists($path)){
			$contents = file_get_contents($path);
			//シリアル化されたレジスタを変数に戻す
			$register = unserialize($contents);
		}
		
		$flg = false;
		if(count($register)>0){
			//すでに登録されていないかチェックする
			foreach($register as $hostport){
				if((strcmp($hostport[0],$host)==0)&&(strcmp($hostport[1],$port)==0)){
					$flg = true;
				}
			}
		}
		
		if($flg==false){
			//未登録なのでキューに追加
			$register[] = array($host,$port,$audio_type);
			//変更したのでシリアライズして保存
			$contents = serialize($register);
			file_put_contents($path,$contents);
		}
		
		$rows='';
		if(count($register)>0){
			foreach($register as $hostport){
				$rows .= "<register>\n"
						."<host>".$hostport[0]."</host>\n"
						."<port>".$hostport[1]."</port>\n"
						."<audio_type>".$hostport[2]."</audio_type>\n"
						."<register>\n";
			}
		}
		
		//レジスタ一覧を返す
		header('Content-type: application/java');
		echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
		echo "<nicosb>\n"
			.$rows
			."</nicosb>";
	}
	
	//通知受け取り
	function notify($path){
		$cmd = (array_key_exists('cmd',$_GET))?htmlspecialchars($_GET['cmd']):'';
		
		$notify = array();

		if(file_exists($path)){
			$contents = file_get_contents($path);
			//変数に戻す
			$notify = unserialize($contents);
		}

		//レスポンス切り替え
		if(strcmp($cmd,'show')==0){
			$rows='';
			if(count($notify)>0){
				foreach($notify as $agent){
				
					//シリアル番号削除
					//Vodafone/1.0/V905SH/SHJ002/SN358150005173738 Browser/VF-NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1
					$pos = strpos($agent,'/SN');
					$agent = substr($agent,0,$pos);
			
					$rows .= "<notify>\n"
							."<agent>".$agent."</agent>\n"
							."<notify>\n";
				}
			}
			
			//一覧を返す
			header('Content-type: application/java');
			echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
			echo "<nicosb>\n"
				.$rows
				."</nicosb>";
		}
		else{
			//アクセスしてきたエージェントを取得
			$user_agent = htmlspecialchars($_SERVER['HTTP_USER_AGENT'],ENT_QUOTES);
			
			if(strcmp($user_agent,'')!=0){
				$notify[] = $user_agent;
				
				//変更したのでシリアライズして保存
				$contents = serialize($notify);
				file_put_contents($path,$contents);
			}
			
			echo "OK";
		}
	}
	
	//インストール通知
	function install_notify(){
		$path = $this->conf->cachedir.'/install_notify';
		$this->notify($path);
	}
	
	//削除通知
	function delete_notify(){
		$path = $this->conf->cachedir.'/delete_notify';
		$this->notify($path);
	}
	
	//キャッシュファイルアップロードフォーム
	//.htaccess
	//php_value post_max_size 20M
	//php_value upload_max_filesize 10M
	//php.ini
	// php_zip.dll
	function upload(){
		$result = false;
		if(array_key_exists('moviepkg',$_FILES)){
			$tmp_name = $_FILES['moviepkg']['tmp_name'];
			
			$name = basename($_FILES['moviepkg']['name']);
			$path_parts = pathinfo($name);
			$ext		= $path_parts['extension'];
			//拡張子チェック
			if(strcmp($ext,'zip')==0){
				$filename = $this->conf->basedir.'/'.basename($name);
				$dir	  = $this->conf->basedir.'/'.basename($name,'.zip');
				//zipファイル,フォルダが無かったらコピー
				if ((!file_exists($filename))&&(!file_exists($dir))&&(is_uploaded_file($tmp_name))){
					$result = @move_uploaded_file( $tmp_name, $filename);
					if($result){
						//アップロード成功したので zip展開
						$cmd = $this->conf->unzip.' '.$filename.' -d '.$this->conf->basedir;
						exec($cmd,$log);
						//展開が済んだのでzip削除
						@unlink($filename);
						//[ToDo]展開後のフォルダ内に危ないファイルが無い事をチェックする事
						
					}
				}
			}
		}
		
		$ret = ($result)?'true':'false';
		
		header('Content-type: application/java');
		echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
		echo "<nicosb>".$ret."</nicosb>";
	}
	
	//FTPでキャッシュファイをファイルアップロードする
	//クーロン内で呼び出し
	function ftp_upload($sm_id=''){
		if(strcmp($sm_id,'')==0){
			$sm_id = (array_key_exists('sm_id',$_GET))?$_GET['sm_id']:'';
		}
		if(strcmp($sm_id,'')==0) return;
		$src_dir = $this->conf->basedir.'/'.$sm_id.'/';
		$dst_dir = $this->conf->ftp_dstdir.'/'.$sm_id;
		if(is_dir($src_dir)){
			//FTP
			$conn_id = ftp_connect($this->conf->ftp_server,$this->conf->ftp_server_port);
			$login_result = ftp_login($conn_id, $this->conf->ftp_user_name, $this->conf->ftp_user_pass);
			//アップロ－ド先ディレクトリ作成
			@ftp_mkdir($conn_id, $this->conf->ftp_dstdir);
			@ftp_mkdir($conn_id, $dst_dir);
			
			$this->ftp_putAll($conn_id, $src_dir, $dst_dir);
			ftp_close($conn_id);
		}
	}
	
	//FTPで指定したディレクトリをアップロードする
	function ftp_putAll($conn_id, $src_dir, $dst_dir) {
		$d = dir($src_dir);
		while($file = $d->read()) { // do this for each file in the directory
			if ($file != "." && $file != "..") { // to prevent an infinite loop
				if (is_dir($src_dir."/".$file)) { // do the following if it is a directory
				   if (!@ftp_nlist($conn_id, $dst_dir."/".$file)) {
				       ftp_mkdir($conn_id, $dst_dir."/".$file); // create directories that do not yet exist
				   }
				   ftp_putAll($conn_id, $src_dir."/".$file, $dst_dir."/".$file); // recursive part
				} else {
				   $upload = ftp_put($conn_id, $dst_dir."/".$file, $src_dir."/".$file, FTP_BINARY); // put the files
				}
			}
		}
		$d->close();
	}
	
	//flvのダウンロード
	function getYoutubeFlv($url,$flvpath){
		$cmd = $this->conf->wget.' -r -O '.$flvpath.' "'.$url.'"';
		$ret = exec($cmd,$log);
	}
	
	//http://www.developer0000.jp/2007/02/18/youtubeiflv/
	//07/12/01
	//http://d.hatena.ne.jp/sed/20071119/1195496546
	//YoutubeのFLVのURLを取得
	function getYoutubeFlvURL( $movieid ){
		if($movieid == "") return "";

		$youtubeurl = $this->conf->youtube_v.$movieid;
		//$response 	= HTTP_HEADER_UTIL::get_http_header($youtubeurl);
		
		//Location を取得
		//$location = $response["Location"];
		$contents = file_get_contents($youtubeurl);
		
		//&t= を抽出
		$pattern = '&t=([^&]+)';
		$t = "";
		if( preg_match ( "/".$pattern."/i", $contents, $match ) ){
			$t = $match[1];
		}
		
		//http://www.youtube.com/get_video?video_id=\&t=
		$flvurl = $this->conf->youtube_get_video.'?video_id='.$movieid.'&t='.$t;
		
		return $flvurl;
	}
	
	function getflv(){
		$sm_id 	= (array_key_exists("sm_id",$_GET))?$_GET["sm_id"]:'';
		
		$flv = $this->conf->cachedir.'/'.basename($sm_id).'.flv';
		
		if(!file_exists($flv)){
			header('HTTP/1.0 404 Not Found');
		}
		else{
			$length = filesize($flv);
			
			header('Content-type: video/x-flv');
			header('Content-Length: '. $length );
			$handle = fopen($flv, 'rb');
			while (!feof($handle)) {
				echo fread($handle, 8192);
			}
			fclose($handle);
		}
	}
}

//一覧の必要情報を保存するクラス
class Movie{
	var $id;
	var $max_file_cnt;
	var $date;
	var $img;
	var $title;
	var $time;
	var $comment;
	var $res;
}

//getflvの返すパラメータを格納するクラス
class NicoapiParam{
	var $thread_id;
	var $l;
	var $url;
	var $link;
	var $ms;
	var $user_id;
	var $is_premium;
	var $nickname;
	var $time;
	var $done;
}

?>